home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / mosmllib / Nonstdio.sml < prev    next >
Encoding:
Text File  |  1996-07-03  |  9.2 KB  |  325 lines  |  [TEXT/R*ch]

  1. (* Nonstdio.sml *)
  2.  
  3. (*
  4.   This unit extends BasicIO. Since Moscow ML doesn't provide
  5.   legal means for creating "derived" units, we have to use some
  6.   "magic", to get into abstract Basicio.instream and
  7.   Basicio.outstream values.
  8.  
  9.   The same problem arises with CharArray.array values.
  10. *)
  11.  
  12. open BasicIO;
  13.  
  14. (* Caml Light "channels" *)
  15.  
  16. (* We define in_channel and out_channel as in Basicio *)
  17. (* for internal use only. *)
  18.  
  19. prim_type in_channel and out_channel;
  20.  
  21. prim_val open_descriptor_in : int -> in_channel = 1 "open_descriptor";
  22.         (* [open_descriptor_in fd] returns a buffered input channel
  23.            reading from the file descriptor [fd]. The file descriptor [fd]
  24.            must have been previously opened for reading, else the behavior is
  25.        undefined. *)
  26.  
  27. prim_val open_descriptor_out : int -> out_channel = 1 "open_descriptor";
  28.         (* [open_descriptor_out fd] returns a buffered output channel
  29.            writing to the file descriptor [fd]. The file descriptor [fd]
  30.            must have been previously opened for writing, else the behavior is
  31.        undefined. *)
  32.  
  33. prim_val input_char_ : in_channel -> char = 1 "input_char";
  34.         (* Read one character from the given input channel.
  35.            Raise [Size] if there are no more characters to read. *)
  36.  
  37. prim_val input_binary_int_ : in_channel -> int = 1 "input_int";
  38.         (* Read an integer encoded in binary format from the given input
  39.            channel. See [output_binary_int].
  40.            Raise [Size] if an end of file was reached while reading the
  41.        integer. *)
  42.  
  43. prim_val input_value_ : in_channel -> 'a = 1 "intern_val";
  44.         (* Read the representation of a structured value, as produced
  45.            by [output_value], and return the corresponding value. *)
  46.  
  47. prim_val seek_in_ : in_channel -> int -> unit = 2 "seek_in"
  48.         (* [seek_in chan pos] sets the current reading position to [pos]
  49.            for channel [chan]. *)
  50.  
  51. prim_val pos_in_ : in_channel -> int = 1 "pos_in";
  52.         (* Return the current reading position for the given channel. *)
  53.  
  54. prim_val in_channel_length_ : in_channel -> int = 1 "channel_size";
  55.         (* Return the total length (number of characters) of the
  56.            given channel. This works only for regular files. *)
  57.  
  58. prim_val fast_input :
  59.   in_channel -> string -> int -> int -> int = 4 "input";
  60.  
  61. prim_val fast_output :
  62.   out_channel -> string -> int -> int -> unit = 4 "output";
  63.  
  64. prim_val output_char_ : out_channel -> char -> unit = 2 "output_char"
  65.         (* Write one character on the given output channel. *)
  66.  
  67. prim_val output_byte_ : out_channel -> int -> unit = 2 "output_char"
  68.         (* Write one 8-bit integer (as the single character with that code)
  69.            on the given output channel. The given integer is taken modulo
  70.            256. *)
  71.  
  72. prim_val output_binary_int_ : out_channel -> int -> unit = 2 "output_int";
  73.         (* Write one integer in binary format on the given output channel. *)
  74.  
  75. prim_val output_value_ : out_channel -> 'a -> unit = 2 "extern_val";
  76.         (* Write the representation of a structured value of any type
  77.            to a channel. *)
  78.  
  79. prim_val seek_out_ : out_channel -> int -> unit = 2 "seek_out"
  80.         (* [seek_out chan pos] sets the current writing position to [pos]
  81.            for channel [chan]. This works only for regular files. On
  82.            files of other kinds (such as terminals, pipes and sockets,)
  83.        the behavior is unspecified. *)
  84.  
  85. prim_val pos_out_ : out_channel -> int = 1 "pos_out";
  86.         (* Return the current writing position for the given channel. *)
  87.  
  88. type file_perm = int;
  89.  
  90. datatype open_flag =
  91.     O_RDONLY                       (* `open' read-only *)
  92.   | O_WRONLY                       (* `open' write-only *)
  93.   | O_RDWR                         (* `open' for reading and writing *)
  94.   | O_APPEND                       (* `open' for appending *)
  95.   | O_CREAT                        (* create the file if nonexistent *)
  96.   | O_TRUNC                        (* truncate the file to 0 if it exists *)
  97.   | O_EXCL                         (* fails if the file exists *)
  98.   | O_BINARY                       (* `open' in binary mode *)
  99.   | O_TEXT                         (* `open' in text mode *)
  100. ;
  101.  
  102. prim_val sys_open :
  103.   string -> open_flag list -> file_perm -> int = 3 "sys_open"
  104.         (* Open a file. The second argument is the opening mode.
  105.            The third argument is the permissions to use if the file
  106.            must be created. The result is a file descriptor opened on the
  107.            file. *)
  108. prim_val sys_close :
  109.   int -> unit = 1 "sys_close"
  110.         (* Close a file descriptor. *)
  111.  
  112.  
  113. (* Moscow ML streams *)
  114.  
  115. type buffer = string;
  116.  
  117. (* Since instream and outstream are declared in Basicio *)
  118. (* as abstract types, we need a dirty trick to get access *)
  119. (* to their representation.  :-< *)
  120.  
  121. type instream_  = { closed: bool, ic: in_channel } ref;
  122. type outstream_ = { closed: bool, oc: out_channel } ref;
  123.  
  124. prim_val fromI : instream -> instream_   = 1 "identity";
  125. prim_val fromO : outstream -> outstream_ = 1 "identity";
  126. prim_val mkI   : instream_ -> instream   = 1 "identity";
  127. prim_val mkO   : outstream_ -> outstream = 1 "identity";
  128.  
  129. (* The same trick to access the internals of CharArray.array. *)
  130.  
  131. prim_val fromCA : CharArray.array -> string ref = 1 "identity";
  132.  
  133. fun open_in_gen_ mode rights filename =
  134.   open_descriptor_in (sys_open filename mode rights)
  135. ;
  136.  
  137. val open_in_bin_ = open_in_gen_ [O_RDONLY, O_BINARY] 0;
  138.  
  139. fun open_out_gen mode rights filename =
  140.   open_descriptor_out(sys_open filename mode rights)
  141. ;
  142.  
  143. prim_val s_irall : file_perm = 0 "s_irall";
  144. prim_val s_iwall : file_perm = 0 "s_iwall";
  145. prim_val s_ixall : file_perm = 0 "s_ixall";
  146.  
  147. val open_out_bin_ =
  148.   open_out_gen [O_WRONLY, O_TRUNC, O_CREAT, O_BINARY]
  149.                (s_irall + s_iwall);
  150.  
  151. val open_out_exe_ =
  152.   open_out_gen [O_WRONLY, O_TRUNC, O_CREAT, O_BINARY]
  153.                (s_irall + s_iwall + s_ixall)
  154. ;
  155.  
  156. fun open_in_bin s =
  157.   mkI (ref {closed=false, ic=open_in_bin_ s})
  158.   handle Io _ =>
  159.     raise Io ("Cannot open "^s)
  160. ;
  161.  
  162. fun fast_really_input is (buff : string) offs len =
  163.   let val ref {closed, ic} = fromI is in
  164.     if closed then
  165.       raise Io "Input stream is closed"
  166.     else if len <= 0 then () else
  167.       case fast_input ic buff offs len of
  168.         0 => raise Fail "fast_really_input: unexpected end of file"
  169.       | r => fast_really_input is buff (offs+r) (len-r)
  170.   end
  171. ;
  172.  
  173. fun buff_input is (buff : CharArray.array) offs len =
  174.   let val ref {closed, ic} = fromI is in
  175.     if closed then
  176.       0
  177.     else
  178.       let val ref sbuff = fromCA buff in
  179.         if len < 0 orelse offs < 0 orelse offs+len > size sbuff then
  180.           raise Fail "buff_input"
  181.         else
  182.           fast_input ic sbuff offs len
  183.       end
  184.   end
  185. ;
  186.  
  187. fun input_char is =
  188.   let val ref {closed, ic} = fromI is in
  189.     if closed then
  190.       raise Io "Input stream is closed"
  191.     else
  192.       input_char_ ic
  193.   end
  194. ;
  195.  
  196. fun input_binary_int is =
  197.   let val ref {closed, ic} = fromI is in
  198.     if closed then
  199.       raise Io "Input stream is closed"
  200.     else
  201.       input_binary_int_ ic
  202.   end
  203. ;
  204.  
  205. fun input_value is =
  206.   let val ref {closed, ic} = fromI is in
  207.     if closed then
  208.       raise Io "Input stream is closed"
  209.     else
  210.       input_value_ ic
  211.   end
  212. ;
  213.  
  214. fun seek_in is =
  215.   let val ref {closed, ic} = fromI is in
  216.     if closed then
  217.       raise Io "Input stream is closed"
  218.     else
  219.       seek_in_ ic
  220.   end
  221. ;
  222.  
  223. fun pos_in is =
  224.   let val ref {closed, ic} = fromI is in
  225.     if closed then
  226.       raise Io "Input stream is closed"
  227.     else
  228.       pos_in_ ic
  229.   end
  230. ;
  231.  
  232. fun in_stream_length is =
  233.   let val ref {closed, ic} = fromI is in
  234.     if closed then
  235.       raise Io "Input stream is closed"
  236.     else
  237.       in_channel_length_ ic
  238.   end
  239. ;
  240.  
  241. fun open_out_bin s =
  242.   mkO(ref {closed=false, oc=open_out_bin_ s})
  243.   handle Io _ =>
  244.     raise Io ("Cannot open "^s)
  245. ;
  246.  
  247. fun open_out_exe s =
  248.   mkO(ref {closed=false, oc=open_out_exe_ s})
  249.   handle Io _ =>
  250.     raise Io ("Cannot open "^s)
  251. ;
  252.  
  253. fun buff_output os (buff : CharArray.array) offs len =
  254.   let val ref {closed, oc} = fromO os in
  255.     if closed then
  256.       raise Io "Output stream is closed"
  257.     else
  258.       let val ref sbuff = fromCA buff in
  259.         if len < 0 orelse offs < 0 orelse offs+len > size sbuff then
  260.           raise Fail "buff_output"
  261.         else
  262.           fast_output oc sbuff offs len
  263.       end
  264.   end
  265. ;
  266.  
  267. fun output_char os (c : char) =
  268.   let val ref {closed, oc} = fromO os in
  269.     if closed then
  270.       raise Io "Output stream is closed"
  271.     else
  272.       output_char_ oc c
  273.   end
  274. ;
  275.  
  276. fun output_byte os (c : int) =
  277.   let val ref {closed, oc} = fromO os in
  278.     if closed then
  279.       raise Io "Output stream is closed"
  280.     else
  281.       output_byte_ oc c
  282.   end
  283. ;
  284.  
  285. fun output_binary_int os i =
  286.   let val ref {closed, oc} = fromO os in
  287.     if closed then
  288.       raise Io "Output stream is closed"
  289.     else
  290.       output_binary_int_ oc i
  291.   end
  292. ;
  293.  
  294. fun output_value os v =
  295.   let val ref {closed, oc} = fromO os in
  296.     if closed then
  297.       raise Io "Output stream is closed"
  298.     else
  299.       output_value_ oc v
  300.   end
  301. ;
  302.  
  303. fun seek_out os pos =
  304.   let val ref {closed, oc} = fromO os in
  305.     if closed then
  306.       raise Io "Output stream is closed"
  307.     else
  308.       seek_out_ oc pos
  309.   end
  310. ;
  311.  
  312. fun pos_out os =
  313.   let val ref {closed, oc} = fromO os in
  314.     if closed then
  315.       raise Io "Output stream is closed"
  316.     else
  317.       pos_out_ oc
  318.   end
  319. ;
  320.  
  321. fun file_exists filename =
  322.   (sys_close(sys_open filename [O_RDONLY] 0); true)
  323.      handle Io _ => false
  324. ;
  325.